﻿

using Emgu.CV;
using Emgu.CV.CvEnum;
using Microsoft.ProjectOxford.Face.Contract;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;

namespace Microsoft.ProjectOxford.Face.Controls
{
    /// <summary>
    /// UI helper functions
    /// </summary>
    internal static class UIHelper
    {
        #region Methods

        /// <summary>
        /// Calculate the rendering face rectangle
        /// </summary>
        /// <param name="faces">Detected face from service</param>
        /// <param name="maxSize">Image rendering size</param>
        /// <param name="imageInfo">Image width and height</param>
        /// <returns>Face structure for rendering</returns>
        public static IEnumerable<FaceInfo> CalculateFaceRectangleForRendering(IEnumerable<Microsoft.ProjectOxford.Face.Contract.Face> faces, Tuple<int, int> imageInfo)
        {
            var imageWidth = imageInfo.Item1;
            var imageHeight = imageInfo.Item2;
            float ratio = (float)imageWidth / imageHeight;
            int uiWidth = imageWidth;
            int uiHeight = imageHeight;
 

            float scale = (float)uiWidth / imageWidth;

            foreach (var face in faces)
            {
                yield return new FaceInfo()
                {
                    FaceId = face.FaceId.ToString(),
                    Left = (int)((face.FaceRectangle.Left * scale)),
                    Top = (int)((face.FaceRectangle.Top * scale)),
                    Height = (int)(face.FaceRectangle.Height * scale),
                    Width = (int)(face.FaceRectangle.Width * scale),
                    Gender = face.FaceAttributes.Gender,
                    Age = string.Format("{0:#}", face.FaceAttributes.Age),
                    Glasses = face.FaceAttributes.Glasses.ToString(),
                    FacialHair = string.Format("{0}", face.FaceAttributes.FacialHair.Moustache + face.FaceAttributes.FacialHair.Beard + face.FaceAttributes.FacialHair.Sideburns > 0 ? "Yes" : "No"),
                    HeadPose = string.Format("Pitch: {0}, Roll: {1}, Yaw: {2}", Math.Round(face.FaceAttributes.HeadPose.Pitch, 2), Math.Round(face.FaceAttributes.HeadPose.Roll, 2), Math.Round(face.FaceAttributes.HeadPose.Yaw, 2)),
                    Emotion = $"{GetEmotion(face.FaceAttributes.Emotion)}",
                    EmotionScores = face.FaceAttributes.Emotion
                };
            }
        }

        private static string GetEmotion(Microsoft.ProjectOxford.Common.Contract.EmotionScores emotion)
        {
            string emotionType = string.Empty;
            double emotionValue = 0.0;
            if (emotion.Anger > emotionValue)
            {
                emotionValue = emotion.Anger;
                emotionType = "愤怒";
            }
            if (emotion.Contempt > emotionValue)
            {
                emotionValue = emotion.Contempt;
                emotionType = "蔑视";
            }
            if (emotion.Disgust > emotionValue)
            {
                emotionValue = emotion.Disgust;
                emotionType = "厌恶";
            }
            if (emotion.Fear > emotionValue)
            {
                emotionValue = emotion.Fear;
                emotionType = "恐惧";
            }
            if (emotion.Happiness > emotionValue)
            {
                emotionValue = emotion.Happiness;
                emotionType = "幸福";
            }
            if (emotion.Neutral > emotionValue)
            {
                emotionValue = emotion.Neutral;
                emotionType = "中性";
            }
            if (emotion.Sadness > emotionValue)
            {
                emotionValue = emotion.Sadness;
                emotionType = "悲伤";
            }
            if (emotion.Surprise > emotionValue)
            {
                emotionValue = emotion.Surprise;
                emotionType = "惊喜";
            }
            return $"{emotionType}";
        }
        

        /// <summary>
        /// Append detected face to UI binding collection
        /// </summary>
        /// <param name="collections">UI binding collection</param>
        /// <param name="path">Original image path, used for rendering face region</param>
        /// <param name="face">Face structure returned from service</param>
        public static void UpdateFace(ObservableCollection<FaceInfo> collections, string path, Microsoft.ProjectOxford.Face.Contract.AddPersistedFaceResult face)
        {
            collections.Add(new FaceInfo()
            {
                ImagePath = path,
                FaceId = face.PersistedFaceId.ToString(),
            });
        }

        /// <summary>
        /// Append detected face to UI binding collection
        /// </summary>
        /// <param name="collections">UI binding collection</param>
        /// <param name="path">Original image path, used for rendering face region</param>
        /// <param name="face">Face structure returned from service</param>
        public static void UpdateFace(ObservableCollection<FaceInfo> collections, string path, Microsoft.ProjectOxford.Face.Contract.Face face)
        {
            collections.Add(new FaceInfo()
            {
                ImagePath = path,
                Left = face.FaceRectangle.Left,
                Top = face.FaceRectangle.Top,
                Width = face.FaceRectangle.Width,
                Height = face.FaceRectangle.Height,
                FaceId = face.FaceId.ToString(),
            });
        }

        /// <summary>
        /// Logging helper function
        /// </summary>
        /// <param name="log">log output instance</param>
        /// <param name="newMessage">message to append</param>
        /// <returns>log string</returns>
        public static string AppendLine(this string log, string newMessage)
        {
            return string.Format("{0}[{3}]: {2}{1}", log, Environment.NewLine, newMessage, DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
        }

        /// <summary>
        /// 获得用于渲染的图片信息
        /// </summary>
        /// <param name="imageFilePath"></param>
        /// <returns></returns>
        public static Tuple<int, int> GetImageInfoForRendering(string imageFilePath)
        {
            try
            {
                IImage image = new UMat(imageFilePath, ImreadModes.Color);

                // Store image width and height for following rendering
                return new Tuple<int, int>(image.Bitmap.Width, image.Bitmap.Height);

            }
            catch
            {
                return new Tuple<int, int>(0, 0);
            }
        }
        #endregion Methods
    }
}